package org.rcgwt.client.ui.grid.renderer;

import org.rcgwt.client.theme.CssStyle;
import org.rcgwt.client.ui.grid.internal.model.ICellModel;
import org.rcgwt.client.ui.grid.internal.model.IColumnModel;
import org.rcgwt.client.ui.grid.internal.model.IGridModel;
import org.rcgwt.client.ui.grid.internal.model.IRowModel;
import org.rcgwt.client.ui.grid.internal.model.IViewModel;
import org.rcgwt.client.ui.grid.theme.IGridTheme;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.TableCellElement;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.TableSectionElement;

/**
 * Default Row Renderer Define Row Id
 * 
 * @author Olivier Oeuillot
 * 
 */
public class DefaultRowRenderer extends AbstractRenderer<IRowModel> implements
		IRowRenderer {

	/**
	 * 
	 */
	public Element render(IViewRenderContext viewRenderContext,
			Element parentElement, IRowModel rowModel, int renderedIndex) {

		assert parentElement instanceof TableSectionElement : "Invalid parent type ("
				+ parentElement + ")";

		TableRowElement rowElement = parentElement.getOwnerDocument()
				.createTRElement();

		update(viewRenderContext, rowElement, rowModel, renderedIndex);

		return rowElement;
	}

	@Override
	public void update(IViewRenderContext viewRenderContext,
			Element rowElement, IRowModel rowModel, int renderedIndex) {
		super.update(viewRenderContext, rowElement, rowModel, renderedIndex);

		viewRenderContext.getViewModel().getViewModelElements().setRowElement(
				rowModel, rowElement, renderedIndex, true);
	}

	@Override
	protected CssStyle getCssStyle(IViewRenderContext viewRenderContext,
			IRowModel row) {
		IGridRenderContext gridRenderContext = viewRenderContext
				.getGridRenderContext();

		return gridRenderContext.getTheme().getRowStyleName(null, row);
	}

	@Override
	protected void updateContent(IViewRenderContext viewRenderContext,
			Element rowElement, IRowModel rowModel) {
		Log.debug("Update content of row " + rowModel.getModelIndex());

		IGridRenderContext gridRenderContext = viewRenderContext
				.getGridRenderContext();

		IViewModel viewModel = viewRenderContext.getViewModel();
		IGridModel gridModel = viewModel.getGridModel();

		IGridTheme theme = gridRenderContext.getTheme();

		viewModel.getViewModelElements()
				.clearCellElements(rowModel, rowElement);

		int cellElementsCount = 0;
		NodeList<TableCellElement> cellElements = null;

		if (rowElement.hasChildNodes()) {
			cellElements = TableRowElement.as(rowElement).getCells();
			cellElementsCount = cellElements.getLength();
		}

		int columnModelIndexes[] = gridRenderContext.getColumnModelIndexes();

		IColumnModel columnModels[] = gridModel.listColumnModels();

		int renderedColumnIndex = 0;
		for (; renderedColumnIndex < columnModelIndexes.length; renderedColumnIndex++) {
			int columnModelIndex = columnModelIndexes[renderedColumnIndex];

			IColumnModel columnModel = columnModels[columnModelIndex];

			ICellModel cell = rowModel.setupSharedCellModel(columnModel);

			if (renderedColumnIndex < cellElementsCount) {
				Element cellElement = cellElements.getItem(renderedColumnIndex);

				updateChild(viewRenderContext, theme, cellElement, cell,
						renderedColumnIndex);
				continue;
			}

			Element cellElement = renderChild(viewRenderContext, theme,
					rowElement, cell, renderedColumnIndex);

			rowElement.appendChild(cellElement);
		}

		for (; renderedColumnIndex < cellElementsCount; cellElementsCount--) {
			Element cellElement = cellElements.getItem(renderedColumnIndex);

			rowElement.removeChild(cellElement);
		}
	}

	protected void updateChild(IViewRenderContext viewRenderContext,
			IGridTheme theme, Element cellElement, ICellModel cell,
			int renderedIndex) {

		IRenderer<ICellModel> cellRenderer = theme.getCellRenderer(cell);

		cellRenderer
				.update(viewRenderContext, cellElement, cell, renderedIndex);

	}

	protected Element renderChild(IViewRenderContext viewRenderContext,
			IGridTheme theme, Element rowElement, ICellModel cell,
			int renderedIndex) {

		IRenderer<ICellModel> cellRenderer = theme.getCellRenderer(cell);

		Element cellElement = cellRenderer.render(viewRenderContext,
				rowElement, cell, renderedIndex);

		return cellElement;
	}

	@Override
	public Element getCellElement(Element rowElement, ICellModel cellModel,
			int renderedIndex) {
		TableRowElement tableRowElement = TableRowElement.as(rowElement);

		return tableRowElement.getCells().getItem(renderedIndex);
	}

}
